package com.zkjl.protect_business.utils;

import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.zkjl.protect_business.common.BaseException;
import com.zkjl.protect_business.common.Status;
import com.zkjl.protect_business.entity.DocField;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static com.zkjl.protect_business.common.Status.BAD_REQUEST;

/**
 * 导出工具类
 */
@Component
public class ExportUtil {


    @Value(value = "${file.export.url}")
    String exportUrl;



    /**
     * 处理集合成有序的
     * @param list
     * @param fields
     * @return
     */
    public static List<LinkedHashMap<String, Object>> toDealWithHashMap(List<Map<String, Object> > list, List<DocField> fields) {

        List<LinkedHashMap<String, Object>> collect = list.stream().map(o -> {
            Map<String, Object> objectMap = (Map<String, Object>) o;
            LinkedHashMap<String, Object> map = new LinkedHashMap<>();
            fields.stream().forEach(field -> {
                String key = field.getKey();
                Object value = objectMap.get(key);
                map.put(key, value);
            });
            return map;
        }).collect(Collectors.toList());

        return collect;

    }

    /**
     * 处理集合 只取字段有的值
     * @param list
     * @param fields
     * @return
     */
    public static List<Map<String, Object>> toDealWithMap(List<Map<String, Object> > list, List<DocField> fields) {

        List<Map<String, Object>> collect = list.stream().map(o -> {
            Map<String, Object> objectMap = (Map<String, Object>) o;
            Map<String, Object> map = new LinkedHashMap<>();
            fields.stream().forEach(field -> {
                String key = field.getKey();
                Object value = objectMap.get(key);
                if (value == null) {
                    map.put(key, " ");
                }else {
                    map.put(key, value);
                }
            });
            return map;
        }).collect(Collectors.toList());

        return collect;

    }



    /**
     * 处理写入数量key长度不一的情况
     * @param collect
     */
    public static List<LinkedHashMap<String, Object>> toDealWithKey(List<LinkedHashMap<String, Object>> collect) {

        List<String> keys = new ArrayList<>();

        //获取所有的key
        collect.stream().forEach(map -> {
            Set<Map.Entry<String, Object>> entries = map.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                String key = entry.getKey();
                if (keys.contains(key)) {
                    continue;
                }
                keys.add(key);
            }

        });

        //给没有值得添加空值
        List<LinkedHashMap<String, Object>> collect1 = collect.stream().map(map -> {
            LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<String, Object>();
            for (String key : keys) {

                boolean containsKey = map.containsKey(key);
                if (containsKey) {
                    linkedHashMap.put(key, map.get(key));
                } else {
                    linkedHashMap.put(key, null);
                }

            }
            return linkedHashMap;

        }).collect(Collectors.toList());

        return collect1;
    }

    /**
     * 回写数据
     * @param collect
     * @param path
     * @throws IOException
     */
    public static File  returnData(String sourcePath,List<Map<String, Object> > collect, String fileName, List<DocField> fields, String path) throws IOException {

        //处理没有的key
        List<LinkedHashMap<String, Object>> linkedHashMap = toDealWithHashMap(collect, fields);
        List<LinkedHashMap<String, Object>> linkedHashMaps = toDealWithKey(linkedHashMap);

        Assert.notNull(fileName, "导出文件名不能为空");

        if (!path.endsWith("/")) {
            path = path + File.separator;
        }
        String simpleUUID = IdUtil.simpleUUID();
        String newPath = path + simpleUUID + "/";

        File dir = new File(newPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        String tmpPath = newPath + fileName;
        //复制模板到新路径
        FileUtil.copy(sourcePath, tmpPath, true);

        //文件后缀名
        String extName = FileUtil.extName(fileName);
        ExcelWriter writer = null;
        if ("xls,xlsx".contains(extName.toLowerCase())) {
            writer = ExcelUtil.getWriter(tmpPath);
        } else {
            throw new BaseException(Status.BAD_REQUEST.getCode(), "导出的模板异常，excel模板后缀应该为 .xls 或者 .xlsx");
        }

        //获取模板的行号
        Integer index = ExportUtil.getIndex(fields);
        writer.setCurrentRow(index + 1);

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(linkedHashMaps, false);

        writer.autoSizeColumnAll();

        try {

            writer.flush();
            // 关闭writer，释放内存
            writer.close();

        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(Status.ERROR.getCode(), "导出文件异常！");
        }
        return new File(tmpPath);
    }


    /**
     * 处理类型转换
     * @param timeStr 时间字段中文名称 用、分隔
     * @param val   值
     * @param key key
     * @return
     */
    public String getName(String timeStr,Object val,String key) {
        String result = val + "";
        if (timeStr.contains(key)) {

            if (val != null) {
                DateTime date = DateUtil.date((Long) val);
                result = date.toString();
            }
        }

        if (val == null) {
            return null;
        }
        return result;

    }

    /**
     * 获取excel起始行号
     * @param docFields
     * @return
     */
    public static Integer getIndex(List<DocField> docFields) {

        DocField docField1 = docFields.get(0);
        String location = docField1.getLocation();
        if (StringUtils.isBlank(location)) {
            throw new BaseException(BAD_REQUEST.getCode(), "该模板字段异常，请重新上传模板后操作！");
        }

        String[] split = location.split(",");
        Integer index = Integer.valueOf(split[0]);  //标题所在序号
        return index;
    }


}
